﻿using Nemerle.Assertions;
using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;

namespace Nemerle2.Compiler
{
  /// <summary>
  /// A global environment. Instance of this type contains set of opened namespaces/types and defined aliases.
  /// This type also manage current active syntax extensions (which has been opened by "using" directive).
  /// </summary>
  [Record]
  public class GlobalEnv
  {
    public Project : NProject;

    /// Include all opened namespaces (include "CurrentNamespace") and types.
    /// String represent dot separate path.
    public OpenedPaths : Set[string]; // здесь нельзя испоьзовать векти дерева типов, так как они еще могут быть не загружены!
    /// String represent dot separate path.
    public CurrentNamespace     : string; // здесь нельзя испоьзовать векти дерева типов, так как они еще могут быть не загружены!
    public Aliases              : Map[string, LocatedList[PId]]; //TODO: hc: turn to PExpr
    //public SyntaxExtensions     : list[SyntaxExtension];

    /// Create root globall env
    /// <param name="project">The current project.</param>
    internal this([NotNull] project : NProject, pathsToOpen : array[string])
    {
      Project             = project;
      CurrentNamespace    = "";
      OpenedPaths         = Set(pathsToOpen);
      Aliases             = Map();
      //SyntaxExtensions      = [];
    }

    /// <param name="prototype">Base GlobalEnv</param>
    /// <param name="currentNamespace">The namespace to set as current (ignored if null)</param>
    /// <param name="namespaceToOpen">The namespace to open (ignored if null)</param>
    public this([NotNull] prototype : GlobalEnv, currentNamespace : string, pathsToOpen : list[string], aliases : list[string * LocatedList[PId]])
    {
      Project = prototype.Project;

      CurrentNamespace = currentNamespace ?? prototype.CurrentNamespace;

      match (pathsToOpen)
      {
        | [] | null => OpenedPaths = prototype.OpenedPaths;
        | _         => OpenedPaths = prototype.OpenedPaths.AddList(pathsToOpen);
      }

      match (aliases)
      {
        | [] | null => Aliases = prototype.Aliases;
        | _         => Aliases = prototype.Aliases.AddList(aliases);
      }
    }
  }
}
